﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace game
{
    public class ObjectTracePSystem : BillboardParticleSystem
    {
        protected enum LifetimePolicy
        {
            EXACT,
            IN_RANGE,
            SINUS_OFFSET,
        }

        protected enum SizePolicy
        {
            WIDTH_EXACT,
            WIDTH_IN_RANGE
        }

        protected LifetimePolicy lifetimePolicy;
        protected SizePolicy sizePolicy;


        public ObjectTracePSystem(Scene scene, Vector3 position)
            : base(scene, position)
        {
            oldPosition = position;
        }

        protected override void InitParameters()
        {
            textureName = "Textures\\whitegradient";
            effectName = "Effects\\BillboardParticle";
            effectTechName = "DynamicAxisAlignedBillboardParticleAdditiveBlending";

            Acceleration = -0.00f;
            maxParticles = 600;

            emitTimeAccumMs = 50.0f;

            emitter = new ParticleEmitter(this, emitTimeAccumMs, position);

            MinInitialSpeed = 10.0f;
            MaxInitialSpeed = 10.0f;
            MinInitialSize = 120.0f;
            MaxInitialSize = 120.0f;
            MinLifeTimeMs = 460;
            MaxLifeTimeMs = 460;

            color = Color.White;

            lifetimePolicy = LifetimePolicy.SINUS_OFFSET;
            sizePolicy = SizePolicy.WIDTH_EXACT;
        }

        protected Vector3 oldPosition;

        protected override void InitParticle(int index, Vector3 position, float initialTimeMsOffset)
        {
            //if (velocity.LengthSquared() < 0.01f)
            //    return;

            Vector3 movement;
            Vector3.Subtract(ref position, ref oldPosition, out movement);

            Vector3 halfMovement;
            Vector3.Multiply(ref movement, 0.5f, out halfMovement);

            float halfMovementLength = halfMovement.Length();

            Vector3 centeredPosition;
            Vector3.Add(ref oldPosition, ref halfMovement, out centeredPosition);

            movement.Normalize();
            Vector3 sideOffset;
            Vector3 upOffset = Vector3.Up;
            Vector3.Cross(ref movement, ref upOffset, out sideOffset);
            

            oldPosition = position;

            float iniTime = elapsedSystemTimeMs + initialTimeMsOffset;
            vertices[index].InitialTimeMs = iniTime;
            vertices[index + 1].InitialTimeMs = iniTime;
            vertices[index + 2].InitialTimeMs = iniTime;
            vertices[index + 3].InitialTimeMs = iniTime;

            float width;
            if (sizePolicy == SizePolicy.WIDTH_EXACT)
            {
                width = MinInitialSize;
            }
            else
            {
                width = RandomHelper.RandomBetween(MinInitialSize, MaxInitialSize);
            }
            vertices[index].Offset.X = -width;
            vertices[index].Offset.Y = -halfMovementLength;
            vertices[index + 1].Offset.X = width;
            vertices[index + 1].Offset.Y = -halfMovementLength;
            vertices[index + 2].Offset.X = width;
            vertices[index + 2].Offset.Y = halfMovementLength;
            vertices[index + 3].Offset.X = -width;
            vertices[index + 3].Offset.Y = halfMovementLength;

            float dieTime;
            if (lifetimePolicy == LifetimePolicy.EXACT)
            {
                dieTime = MinLifeTimeMs;
            }
            else if (lifetimePolicy == LifetimePolicy.IN_RANGE)
            {
                dieTime = RandomHelper.RandomBetween(MinLifeTimeMs, MaxLifeTimeMs);
            }
            else
            {
                float lifetimeWave = (float)Math.Sin(elapsedSystemTimeMs * 0.001f) * 60.0f;
                dieTime = lifetimeWave + MinLifeTimeMs;
            }
            
            vertices[index].DieTimeMs = dieTime;
            vertices[index + 1].DieTimeMs = dieTime;
            vertices[index + 2].DieTimeMs = dieTime;
            vertices[index + 3].DieTimeMs = dieTime;

            
            vertices[index].InitialColor = color;
            vertices[index + 1].InitialColor = color;
            vertices[index + 2].InitialColor = color;
            vertices[index + 3].InitialColor = color;

            vertices[index].TexCoord = new Vector2(1, 1);
            vertices[index + 1].TexCoord = new Vector2(0, 1);
            vertices[index + 2].TexCoord = new Vector2(0, 0);
            vertices[index + 3].TexCoord = new Vector2(1, 0);

            vertices[index].InitialPosition = centeredPosition;
            vertices[index + 1].InitialPosition = centeredPosition;
            vertices[index + 2].InitialPosition = centeredPosition;
            vertices[index + 3].InitialPosition = centeredPosition;

            vertices[index].Axis = movement;
            vertices[index + 1].Axis = movement;
            vertices[index + 2].Axis = movement;
            vertices[index + 3].Axis = movement;

            
        }
    }
}
